/**
 * Created with CLion.
 * Description: 
 * User: loong
 * Date: 2024/8/30
 * Time: 17:00
 */

#include "Client.h"
#include <Content.pb.h>

using namespace std::chrono_literals;

Client::Client(const std::string & name)
    : context_(1)
    , snapshot_sync_(context_, zmq::socket_type::dealer)
    , subscriber_(context_, zmq::socket_type::sub)
    , publisher_(context_, zmq::socket_type::push)
    , name_(name)
{
    subscriber_.set(zmq::sockopt::subscribe, "");
    snapshot_sync_.set(zmq::sockopt::routing_id, name_);
    snapshot_sync_.connect("tcp://localhost:11556");
    subscriber_.connect("tcp://localhost:11557");
    publisher_.connect("tcp://localhost:11558");

    // 获取最后刷新序号
    settings_ = new QSettings(qApp->applicationDirPath() + "/../config/client.ini", QSettings::IniFormat);
    settings_->setIniCodec("utf-8");
    sequence_ = settings_->value("LastID/sequence").toInt();

    //test
    timer_.setInterval(20ms);
    timer_.setSingleShot(false);
    QObject::connect(&timer_, &QTimer::timeout, [=] {
        std::cout << "timer start" << std::endl;
        Chat::Internal::SingleMessage message;

        static int i = 0;
        message.clear_sequence();
        message.set_clientid(name_);
        message.set_content(std::string(1, 'A' + i++ % 26));

        SendMessage(message);
    });
    timer_.start();
}

Client::~Client()
{
    if(nullptr != settings_) {
        delete settings_;
        settings_ = nullptr;
    }
}

void Client::Run()
{
    // 上线发送快照同步请求
    Chat::Internal::LogInMessage message;
    message.set_lastid(sequence_);

    std::string serialized_message;

    bool ret = message.SerializeToString(&serialized_message);
    assert(ret);

    snapshot_sync_.send(zmq::message_t(serialized_message), zmq::send_flags::none);

    while(true) {
        zmq::pollitem_t items[] = {
                {static_cast<void *>(subscriber_), 0, ZMQ_POLLIN, 0},
                {static_cast<void *>(snapshot_sync_), 0, ZMQ_POLLIN, 0},
        };
        zmq::poll(items, 2, 1000);

        // 服务端主题数据接收
        if(items[0].revents & ZMQ_POLLIN) {
            zmq::message_t message;
            subscriber_.recv(message, zmq::recv_flags::none);

            Chat::Internal::SingleMessage msg;

            bool ret = msg.ParseFromArray(message.data(), message.size());
            assert(ret);

            std::cout << "receive " << msg.clientid() << " message:" << msg.sequence() << " " << msg.content() << std::endl;
        }

        // 历史同步信息接收 (仅上线时使用)
        if(items[1].revents & ZMQ_POLLIN) {
            zmq::message_t message;
            snapshot_sync_.recv(message, zmq::recv_flags::none);

            Chat::Internal::CombMessage comb_message;

            bool ret = comb_message.ParseFromString(message.to_string());
            assert(ret);
        }

        qApp->processEvents();
    }
}

void Client::SendMessage(const Chat::Internal::SingleMessage & message)
{
    //发送时无需指定序列号，由服务端按接收顺序统一排序
    assert(message.sequence() == 0);
    std::string serialized_message;

    bool ret = message.SerializeToString(&serialized_message);
    assert(ret);

    publisher_.send(zmq::message_t(serialized_message), zmq::send_flags::none);
    std::cout << name_ << " send : " << serialized_message << std::endl;
}